home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1989
/
02
/
memmove.asm
< prev
next >
Wrap
Assembly Source File
|
1989-01-31
|
4KB
|
196 lines
; a fast MEMMOVE routine that uses the 80836 if present
; this function can replace the memmove routine supplied with
; Microsoft and Borland C runtime libraries (sample coded in
; (small model)
;
; Author: M. Steven Baker
; Date: January 19, 1989
; Last Revision: January 31, 1989
;
; added test to force word alignment of source
; PROCEDURE cputype
;
; find out if we have an 80386 CPU to use
; This routine can be used from the real or virtual
; 8086 mode only. Otherwise will likely cause a
; protection violation (PUSHF instruction is
; privileged)
;
; Based on COMPAQ DESKPRO 386/20 Technical Reference Guide
; (originally suggested by INTEL)
;
; Entry: none
; Exit: AX = CPU type
; 0086h if 8088/8086
; 0286h if 80286
; 0386h if 80386
; Stack: 8 bytes
;
.MODEL small
.CODE
public _cputype
_cputype proc near
pushf ;save the real flags register
;
pop ax ;get register off stack
push ax ;and save it again
;
and ax,0fffh ;zero out bits 12-15
push ax
popf ;try to put into flags
pushf
pop ax ;let's see what came out
;of flags
and ax,0F000h ;mask off bits 12-15
cmp ax,0F000h ;were these bits all 1's
je is_86 ;if so, it's an 8086
;
pop ax ;get flags register to AX
push ax ;and save it again
;
or ax,0F000h ;now try to set bits 12-15
push ax
popf ;of the flags register
pushf
pop ax ;and see what came out
and ax,0F000h ;are high bits set
je is_286 ;if so, we have a 386
is_386: mov ax,0386h
jmp short cpu_exit
;
is_286: mov ax,0286h
jmp short cpu_exit
;
is_86: mov ax,86h
;
cpu_exit:
popf ;restore flags
ret
_cputype endp
;
; PROCEDURE memmove
;
; void * memmove(void *dest,const void *src,size_t count);
; returns *dest
public _memmove
_memmove proc near
push bp
mov bp,sp ;use BP to get variables
mov dx,di ;save register variables
mov bx,si ;into BX and DX
mov ax,ds
mov es,ax ;force ES to DS (small model
mov di,[bp+4] ;get destination ptr
mov si,[bp+6] ;and source ptr
mov cx,[bp+8] ;and byte count
;
mov ax,di ;memmove returns dest ptr
jcxz mmov_ret ;if count=0, where done
;
cmp di,si ;do we have possible overlap
jb forward1 ;if not go do it
;
je mmov_ret ;if dest=src, then do nothing
mov ax,si ;
add ax,cx ;find end point of source
cmp di,ax ;do we overlap with dest ?
mov ax,di ;memmove must return dest ptr
jae forward ;no overlap
;
add si,cx ;copy from end of string back
add di,cx
std ;set reverse direction
dec si
dec di
;
test si,1 ;are we at least word aligned?
jz back1
movsb ;get word aligned
dec cx
;
back1: shr cx,1 ;convert to words
jnc back2 ;carry if odd count
movsb
back2: dec si ;set index for word
dec di
shr cx,1
patch_o1:
jnc back4
movsw
back4: sub di,2
sub si,2
db 66h ;operand size [refix
patch_i1:
rep movsw
cld ;force forward direction
mmov_ret:
mov si,bx ;restore register variables
mov di,dx
pop bp
ret
forward1:
test si,1 ;are we at least word aligned?
jz forward
movsb ;get word aligned
dec cx
forward:
shr cx,1 ;byte count to words
jnc forwd4 ;if no carry, then even count
movsb
forwd4: shr cx,1 ;word count to dwords
patch_o2:
db 66h ;operand size prefix
rep movsw ;(rep movsd) move double words
adc cx,cx ;if carry was odd
rep movsw ;if CX<>0 movsw
;
mov si,bx ;restore register variables
mov di,dx
pop bp
ret
_memmove endp
public _cpupatch
_cpupatch proc near
call _cputype
cmp ax,0386h
jne patch_mmove
ret
;
patch_mmove:
push ds ;save registers
push es
push si
push di
push cx
;
mov ax,cs ;set DS=ES to CS
mov ds,ax
mov es,ax
mov si,offset patch_i1 ;input patch
mov di,offset patch_o1
mov cx,(offset forward- offset patch_i1)
rep movsb
;
mov si,offset patch_i1
mov di,offset patch_o2
mov cx,(offset forward - offset patch_i1)
rep movsb
;
pop cx
pop di
pop si
pop es
pop ds
ret
_cpupatch endp
end